package com.zmn.oms.business.impl.remind;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.common.data.common.constant.TagConsts;
import com.zmn.base.common.data.common.dro.tags.TagsDRO;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.business.interfaces.callinfo.CallInfoBService;
import com.zmn.oms.business.interfaces.messageV1.app.MessageSendAppService;
import com.zmn.oms.business.interfaces.remind.OrderRemindBService;
import com.zmn.oms.business.interfaces.xno.OrderXnoBindBService;
import com.zmn.oms.business.interfaces.xno.OrderXnoBindService;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.MessageConsts;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.remind.RemindDTO;
import com.zmn.oms.model.dto.work.xno.XnoBindDTO;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.master.OrderMaster;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.master.OrderMasterService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.track.common.constant.TrackConfigConsts;
import com.zmn.track.common.constant.remind.RemindConsts;
import com.zmn.track.common.dio.remind.RemindDIO;
import com.zmn.track.dubbo.dto.TrackWorkDIO;
import com.zmn.track.dubbo.interfaces.remind.RemindModifyRemoteService;
import com.zmn.track.dubbo.interfaces.trackwork.TrackWorkModifyRemoteService;
import com.zmn.xno.common.enums.AxbBindResCode;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 类描述：工单提醒
 *
 * @author ligang
 * @date 2021/12/08 18:19
 */
@Service
@Slf4j
public class OrderRemindBServiceImpl implements OrderRemindBService {
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private CallInfoBService callInfoBService;
    @Autowired
    private OrderXnoBindBService orderXnoBindBService;
    @Autowired
    private BaseCodeService baseCodeService;
    @Autowired
    private MessageSendAppService messageSendAppService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderMasterService orderMasterService;
    @Autowired
    private OrderXnoBindService orderXnoBindService;
    @Autowired
    private OrderProductService orderProductService;

    @Reference(version = com.zmn.track.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private RemindModifyRemoteService remindModifyRemoteService;

    @Reference(version = com.zmn.track.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private TrackWorkModifyRemoteService trackWorkModifyRemoteService;

    /**
     * 一键提醒（师傅联系用户）
     */
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_ONE_CLICK_REMINDER, beforeProceed = false)
    @Override
    public void remindMasterContactUser(RemindDTO remindDTO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(remindDTO.getOrderId(), remindDTO.getWorkId());
        // 订单详情
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getWorkId());
        if (xnoBindCheck(orderDetail, orderWork)) {
            // 发起跟单
            this.addTrack(remindDTO);
            // 发送消息
            this.sendMsg(orderWork, remindDTO, orderDetail.getBindTelephone());
            return;
        }
        // 绑定小号
        XnoBindDTO xnoBindDTO = remindBindXno(remindDTO.getOrderId(), remindDTO.getWorkId());
        // 无小号地区，操作后不绑定小号，但需向工程师APP推送通知
        if (Objects.equals(xnoBindDTO.getFailCode(), AxbBindResCode.BIND_NO_RESOURCE)) {
            // 发送消息
            this.sendMsg(orderWork,remindDTO, orderDetail.getTelephone());
        } else if (Objects.nonNull(xnoBindDTO.getFailCode()) || StringUtil.isNotBlank(xnoBindDTO.getFailMessage())) {
            log.info("workId={} 一键提醒 绑定失败Code：{}", remindDTO.getWorkId(), xnoBindDTO.getFailCode());
            throw new OmsBaseException("绑定失败，请重试");
        }
        // 发起跟单
        this.addTrack(remindDTO);
        // 发送消息
        this.sendMsg(orderWork, remindDTO, xnoBindDTO.getBindTelephone1());
    }

    /**
     * 添加需工程师再次联系跟单
     *
     * @param remindDTO
     */
    private void addTrack(RemindDTO remindDTO) {
        TrackWorkDIO trackDIO = new TrackWorkDIO();
        trackDIO.setOrderId(remindDTO.getOrderId());
        trackDIO.setWorkId(remindDTO.getWorkId());
        trackDIO.setTrackContentId(TrackConfigConsts.TRACK_CONTENT_ID_ENGINEER_NEEDS_TO_CONTACT_AGAIN);
        trackDIO.setReasonId(TrackConfigConsts.TRACK_REASON_ID_ENGINEER_NEEDS_TO_CONTACT_AGAIN);
        trackDIO.setOperator(com.zmn.common.constant.GlobalConsts.getOperatorTypeName(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
        trackDIO.setOperatorId((long) com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        trackDIO.setOperatorType(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        trackDIO.setOperatorLogRemark(remindDTO.getOperatorLogRemark());
        ResponseDTO responseDTO = trackWorkModifyRemoteService.addTrack(trackDIO);
        if (!responseDTO.isSuccess()) {
            log.info("添加需工程师再次联系跟单 发起跟单-处理失败，入参：{}，出参：{}", JSON.toJSONString(trackDIO), JSON.toJSONString(responseDTO));
        }
    }

    /**
     * 检查小号绑定
     *
     * @param orderDetail
     * @param orderWork
     * @return
     */
    private boolean xnoBindCheck(OrderDetail orderDetail, OrderWork orderWork) throws OmsBaseException {
        List<OrderMaster> masters = orderMasterService.listMasterByWorkId(orderWork.getOrderId(), orderWork.getWorkId(), OrderConsts.ORDER_MASTER_TYPE_MAIN);
        if (CollectionUtil.isNullOrEmpty(masters)) {
            throw new OmsBaseException("工程师信息查询失败");
        }
        OrderMaster orderMaster = masters.get(0);
        // 查询小号
        String telephone = orderDetail.getTelephone();
        String telephone2 = orderDetail.getTelephone2();
        String telephone3 = orderDetail.getTelephone3();
        List<String> phoneList = Lists.newArrayList(telephone, telephone2, telephone3);
        // 师傅手机号
        String masterTelephone = orderMaster.getMasterPhone();
        return phoneList.stream().anyMatch(phone -> StringUtils.isNotBlank(telephone) && orderXnoBindService.queryXNO(masterTelephone, phone, orderWork) != null);
    }

    /**
     * 小号绑定
     *
     * @param orderId
     * @param workId
     * @return
     */
    private XnoBindDTO remindBindXno(Long orderId, Long workId) throws OmsBaseException {
        TagsDRO oneBaseCodeMap = baseCodeService.getOneBaseCodeMap(com.zmn.consts.GlobalConsts.PLAT_MARK_ZMN,
                TagConsts.TAG_REMINDER_XNO_BIND_TIME, null);
        // 单位分钟
        Integer bindTime = oneBaseCodeMap.getTwoTypeId();
        XnoBindDTO xnoBindDTO = new XnoBindDTO();
        xnoBindDTO.setOrderId(orderId);
        xnoBindDTO.setWorkId(workId);
        xnoBindDTO.setOperateTime(new Date());
        xnoBindDTO.setNeedBindFirstXno(true);
        xnoBindDTO.setExpiredDuration(bindTime * 60L);
        orderXnoBindBService.bind(xnoBindDTO);
        return xnoBindDTO;
    }

    /**
     * 发送短信
     *
     * @param orderWork
     * @param remindDTO
     * @throws OmsBaseException
     */
    private void sendMsg(OrderWork orderWork,RemindDTO remindDTO,String telephone) {
        log.info("订单取消后push消息 workId={}", orderWork.getWorkId());
        Map smsMap = Maps.newHashMap();
        smsMap.put("work_id", orderWork.getWorkId());
        smsMap.put("order_id", orderWork.getOrderId());
        smsMap.put("remarks", StringUtils.isBlank(remindDTO.getRemark()) ? "null" : remindDTO.getRemark());
        smsMap.put("telephone", StringUtils.isBlank(telephone) ? "null" : telephone);
        smsMap.put("cause", StringUtils.isBlank(remindDTO.getSceneName()) ? "null" : remindDTO.getSceneName());
        // 产品信息
        List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(orderWork.getOrderId());
        if (CollectionUtils.isNotEmpty(orderProducts)) {
            OrderProduct product = orderProducts.get(0);
            smsMap.put("product_name", StringUtils.isBlank(product.getShowProductName()) ? "null" : product.getShowProductName());
        }
        log.info("workId={} 订单取消后push消息入参:{} ", orderWork.getWorkId(), smsMap);
        boolean res = messageSendAppService.pushAppMessageInfo(MessageConsts.ZMN_MSG_RULEID_CONTACT_REMINDER_AGAIN, JSON.toJSONString(smsMap), orderWork);
        log.info("workId={} msgId={} 订单取消后push消息出参:{} ", orderWork.getWorkId(), MessageConsts.ZMN_MSG_RULEID_CONTACT_REMINDER_AGAIN, res);
    }

    @Override
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_REMINDER, beforeProceed = false)
    public void remindContactMaster(RemindDTO remindDTO) throws OmsBaseException {
        RemindDIO remindDIO = new RemindDIO();
        remindDIO.setOrderId(remindDTO.getOrderId());
        remindDIO.setWorkId(remindDTO.getWorkId());
        remindDIO.setType(RemindConsts.REMIND_TYPE_WORK);
        remindDIO.setAgain(remindDTO.getAgain());
        // 催单场景】，取值于“新单催单/1016”、“返修单催单/1129”跟单内容下关联的 “跟单缘由”，默认选中“用户催单/62
        remindDIO.setReasonId(remindDTO.getSceneId());
        remindDIO.setOperatorType(remindDTO.getOperatorType());
        remindDIO.setOperatorId(remindDTO.getOperatorId());
        remindDIO.setOperator(remindDTO.getOperator());
        remindDIO.setRemark(remindDTO.getRemark());
        log.info("#OrderRemindBServiceImpl#remindContactMaster remindDTO={}", remindDIO);
        ResponseDTO responseDTO = remindModifyRemoteService.addRemind(remindDIO);
        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(responseDTO.getStatus(), responseDTO.getMessage());
        }
    }
}
